#include "./sensor.h"
#include "../xlib/gpio.h"
#include "../rtos/mutex.h"
#include "../xlib/adc.h"

namespace cargo_driver {

Sensor sensor;

namespace sensor_impl {

using namespace stm32f1;
using namespace rtos::lazy;

using PL = gpio::PB<3>;
using CP = gpio::PB<4>;
using Q7 = gpio::PB<5>;

using ADC = gpio::PC<2>;

static Mutex mutex;
static uint16_t adcBuf[1];

}

using namespace sensor_impl;

void Sensor::init() {
    mutex.init();

    rcc::enable<
        PL, CP, Q7, ADC, adc::Adc1, dma::DmaSel<adc::Adc1::BASE_VAL>::CHAN
    >();
    rcc::adc_prescaler_init();
    gpio::config<
        gpio::Cfg<PL, gpio::Mode::OUT_50MHz_PP>,
        gpio::Cfg<CP, gpio::Mode::OUT_50MHz_PP>,
        gpio::Cfg<Q7, gpio::Mode::INPUT_FLOAT>,
        gpio::Cfg<ADC, gpio::Mode::INPUT_ANALOG>
    >();
    adc::config<adc::Adc1, 12>(adcBuf);
}

uint16_t Sensor::adc_value() {
    return adcBuf[0];
}

uint8_t Sensor::read() {
    mutex.lock();

    uint8_t val = 0;
    PL::clr();
    PL::set();
    for (uint8_t i = 0; i < 8; i ++) {
        val <<= 1;
        if (Q7::read()) {
            val ++;
        }
        CP::set();
        CP::clr();
    }

    mutex.un_lock();

    return val;
}

}
